// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

part of dart.core;

/**
 * 通用的比较函数的签名。
 *
 * 比较函数表示一类对象的顺序。
 * 类型的全序关系，意思是对于两个值，要么它们相等，要么一个值比另一个大（后者则比前者小）。
 *
 * [Comparator]函数通过返回值来表示这种全序关系。
 *
 * * 如果[a]小于[b]，返回一个负整数
 * * 如果[a]等于[b]，返回0
 * * 如果[a]大于[b]，返回一个正整数
 */
typedef int Comparator<T>(T a, T b);

/**
 * 类型使用的接口都有一个固有的顺序。
 *
 * [compareTo]操作定义了对象的全序关系，可用来排序和分类。
 *
 * [Comparable]应该使用类型的自然顺序。
 * 如果一个类型有不止一种方式可以被排序，并且它们没有明显的自然顺序，
 * 那么它可能最好不要使用[Comparable]接口，
 * 然后使用单独的[Comparator]代替。
 *
 * 建议[Comparable]的顺序与[==]操作符保持一致（`a.compareTo(b) == 0`，当且仅当`a == b`时），
 * 但这并不是绝对的。
 * 例如，[double]和[DateTime]都有`compareTo`方法，但与[==]操作符的结果并不一样。
 * 对于double，[compareTo]比相等更加的精准；而DateTime并不准确。
 *
 * 例子:
 *
 *      (0.0).compareTo(-0.0);  // => 1
 *      0.0 == -0.0;            // => true
 *      var dt = new DateTime.now();
 *      var dt2 = dt.toUtc();
 *      dt == dt2;              // => false
 *      dt.compareTo(dt2);      // => 0
 *
 * [Comparable]接口并不意味着存在比较操作符`<`，`<=`，`>`和`>=`。
 * 那些只应该被在顺序只是小于/大于时被定义。
 * 也就是说，对于一个排序的两个元素，你会很自然的使用"小于"这样的话。
 *
 * 如果[==]操作符和[compareTo]结果不一致，那么比较操作符应该对照[==]操作符，
 * 然后可能和[compareTo]结果也不一样。
 * 否则，应该匹配[compareTo]方法，
 * 以便当且仅当`a.compareTo(b) < 0`时，`a < b`。
 *
 * [double]类定义了比较操作，并且相互保持了一致。
 * 操作符与`double.compareTo`的不同点在于，比较-0.0和NAN（0.0）的时候。
 *
 * [DateTime]类并没有比较操作符，取而代之，
 * 它有命名更明确的方法[DateTime.isBefore]和[DateTime.isAfter]。
 */
abstract class Comparable<T> {
  /**
   * 将此对象与另一个[Comparable]进行比较。
   *
   * 返回一个值，就像[Comparator]将`this`与[other]进行比较。
   * 也就是说，如果`this`顺序在[other]之前，返回一个负整数，
   * 如果`this`顺序在[other]之后，返回一个正整数，
   * 如果`this`和[other]顺序一样，则返回0。
   *
   * 参数[other]必须是一个可与此对象进行比较的值。
   */
  int compareTo(T other);

  /**
   * 比较一个可比较的值与另一个值的[Comparator]。
   *
   * 它返回`a.compareTo(b)`的结果。
   *
   * 对于容器（collection）排序，例如，[List]中的sort函数，
   * 这个效用函数被当做默认的比较器使用。
   */
  static int compare(Comparable a, Comparable b) => a.compareTo(b);
}
